package mvc.model

import ext.*
import org.json.JSONObject


class Status(byteArray: ByteArray) {
    companion object {
        fun withNormal(): Status {
            return Status(ByteArray(15) { 0 })
        }

        private var tempErrorTimeOut = 30 * 60 // 超时时间
        private var tempValueMax = 0 // 温度最大值
        private var tempValueMin = 0 // 温度最小值
        private var tempErrorCount = 0 // 温度异常计数

        fun setTempValue(max: Int, min: Int, timeOut: Int) {
            tempValueMax = max
            tempValueMin = min
            tempErrorTimeOut = timeOut * 60
            tempErrorCount = 0
            log("温度最大值:$max 最小值:$min 超时时间: $tempErrorTimeOut")
        }

        private fun refreshTempCount(tempValue: Float): Boolean {
            if ((tempValue > tempValueMax) || (tempValue < tempValueMin)) {
                tempErrorCount += 10
            } else {
                tempErrorCount = 0
            }
            return tempErrorCount >= tempErrorTimeOut
        }

        private fun motorStatusWithCode(code: Int): String {
            return when (code) {
                0x01 -> "ok"
                0x02 -> "timeOut"
                0x03 -> "locked"
                else -> "ok"
            }
        }
    }

    private val H7 = byteArray.byteArg(1)
    private val M7 = byteArray.byteArg(2)
    private val L7 = byteArray.byteArg(3)
    private val D1 = byteArray.byteArg(4)
    private val D2 = byteArray.byteArg(5)
    private val D3 = byteArray.byteArg(6)
    private val D4 = byteArray.byteArg(7)
    private val tempValue = byteArray.int16Arg(8)
    private val D5 = byteArray.byteArg(10)
    private val tempValueErrorFlag: Boolean // 温度异常

    val pick1Forward = H7.isMaskClr(0)
    val pick1BackUp = H7.isMaskClr(1)
    val pick2Forward = H7.isMaskClr(2)
    val pick2BackUp = H7.isMaskClr(3)

    val downKey = M7.isMaskClr(0)
    val pickDoorDown = M7.isMaskClr(1)
    val pickDoorUp = M7.isMaskClr(2)
    val upDownUp = M7.isMaskClr(3)

    val leftRightMoveLeft = M7.isMaskClr(5)
    val leftRightMoveRight = M7.isMaskClr(6)

    val doorKey4 = L7.isMaskClr(3)
    val doorKey5 = L7.isMaskClr(4)
    val replenishKey = L7.isMaskClr(5)
    val upKey = L7.isMaskClr(6)

    val pickMotor = D1.bitFieldValue(4, 2)
    val leftForwardMotor = D1.bitFieldValue(0, 2)
    val rightForwardMotor = D2.bitFieldValue(4, 2)
    val leftPickMotor = D2.bitFieldValue(0, 2)
    val rightPickMotor = D3.bitFieldValue(4, 2)
    val leftRightStepMotor = D3.bitFieldValue(0, 2)
    val upDownStepMotor = D4.bitFieldValue(4, 2)

    val leftRightZero = D4.isMaskSet(1)
    val upDownDown = D4.isMaskSet(2)
    val raster = D4.bitFieldValue(0, 1)

    val tempValueFloat: Float
    val tempSensorError = (tempValue and 0x3FFF) == 0x3FFF

    val doorKey1 = D5.isMaskClr(0)
    val doorKey2 = D5.isMaskClr(1)
    val doorKey3 = D5.isMaskClr(2)
    val doorClose = !D5.isMaskClr(3)

    val errorMessage: String
    val trouble: Boolean

    init {
        tempValueFloat = if (tempValue and 0x800 != 0x00) {
            -(0x1000 - (tempValue and 0xFFF)) * 0.0625f
        } else {
            (tempValue and 0xFFF) * 0.0625f
        }
        tempValueErrorFlag = refreshTempCount(tempValueFloat)
        val sb = StringBuilder()
        trouble = isError(sb)
        errorMessage = sb.toString()
    }

    private fun isError(sb: StringBuilder): Boolean {
        var ret = false
        if (pickMotor != 0x01) {
            ret = true
            sb.append("取物门电机故障\r\n")
            log("---pickMotor:$pickMotor")
        }
        if (leftForwardMotor != 0x01) {
            ret = true
            sb.append("左前进电机故障\r\n")
            log("---leftForwardMotor:$leftForwardMotor")
        }
        if (rightForwardMotor != 0x01) {
            ret = true
            sb.append("右前进电机故障\r\n")
            log("---rightForwardMotor:$rightForwardMotor")
        }
        if (leftPickMotor != 0x01) {
            ret = true
            sb.append("左取物电机故障\r\n")
            log("---leftPickMotor:$leftPickMotor")
        }
        if (rightPickMotor != 0x01) {
            ret = true
            sb.append("右取物电机故障\r\n")
            log("---rightPickMotor:$rightPickMotor")
        }
        if (leftRightStepMotor != 0x01) {
            ret = true
            sb.append("左右步进电机故障\r\n")
            log("---leftRightStepMotor:$leftRightStepMotor")
        }
        if (upDownStepMotor != 0x01) {
            ret = true
            sb.append("升降步进电机故障\r\n")
            log("---upDownStepMotor:$upDownStepMotor")
        }
//        if (raster != 0x00) {
//            ret = true
//            sb.append("光栅被遮挡\r\n")
//        }
        if (!doorClose) {
            ret = true
            sb.append("大门打开\r\n")
        }
        if (!pickDoorDown) {
            ret = true
            sb.append("取物门打开\r\n")
        }
        if (tempValueErrorFlag) {
            ret = true
            sb.append("温度异常\r\n")
        }
        if (tempSensorError) {
            ret = true
            sb.append("温度传感器故障\r\n")
        }
        return ret
    }

    fun toJson(): JSONObject {
        val json = JSONObject()
        json.put("getGoodsDoor", motorStatusWithCode(pickMotor))
        json.put("lForward", motorStatusWithCode(leftForwardMotor))
        json.put("rForward", motorStatusWithCode(rightForwardMotor))
        json.put("lGetGoods", motorStatusWithCode(leftPickMotor))
        json.put("rGetGoods", motorStatusWithCode(rightPickMotor))
        json.put("lfStep", motorStatusWithCode(leftRightStepMotor))
        json.put("udStep", motorStatusWithCode(upDownStepMotor))
        json.put("raster", if (raster == 0x00) "nocovered" else "covered")
        json.put("doorStatus", if (doorClose) "close" else "open")
        json.put("pickDoor", if (pickDoorDown) "close" else "open")
        json.put("troubleTemperature", tempValueErrorFlag)
        json.put("trouble", trouble)
        json.put("zt", if (trouble) "malfunction" else "normal")
        json.put("temperatureSensor", if (tempSensorError) "error" else "normal")
        return json
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is Status) return false

        if (H7 != other.H7) return false
        if (M7 != other.M7) return false
        if (L7 != other.L7) return false
        if (D1 != other.D1) return false
        if (D2 != other.D2) return false
        if (D3 != other.D3) return false
        if (D4 != other.D4) return false
        if (D5 != other.D5) return false
        if (tempValueErrorFlag != other.tempValueErrorFlag) return false

        return true
    }

    override fun hashCode(): Int {
        var result = H7
        result = 31 * result + M7
        result = 31 * result + L7
        result = 31 * result + D1
        result = 31 * result + D2
        result = 31 * result + D3
        result = 31 * result + D4
        result = 31 * result + D5
        result = 31 * result + tempValueErrorFlag.hashCode()
        return result
    }
}
